#ifndef FILTER_H
#define FILTER_H

#include <array>
#include <complex>

#include "dmstruct.h"
#include "dmdef.h"
#include "filterconfig.h"

using PairArray = std::array<double, EQ_FREQUENCY_COUNT>;
using cd = std::complex<double>;

class Filter
{
public:

    /*!
     *  @brief 计算频率对应的增益值
     *  @param dm EQ Xover
     *  @return 频率增益图上各个频率对应的增益值，数量和频率EQ_FREQUENCY一致
    */
    static PairArray gainArray(const DMVariant &dm);

    /*!
     *  @brief 频率转宽度占比
     *  @param freq 频率
     *  @return 占比0-1
    */
    static double freqToWidth(const double &freq);

    /*!
     *  @brief 增益转高度占比
     *  @param gain 增益
     *  @return 占比0-1
    */
    static double gainToHeight(const double &gain);

    /*!
     *  @brief 宽度转频率
     *  @param w 最大宽度
     *  @param width 实际宽度
     *  @return 频率
    */
    static double widthToFreq(const double &w, const double &width);

    /*!
     *  @brief 高度转增益
     *  @param w 最大高度
     *  @param height 实际高度
     *  @return 增益
    */
    static double heightToGain(const double &h, const double &height);

    /*!
     *  @brief 带宽转Q值
     *  @param bw 带宽 * 100
     *  @return Q值
    */
    static double bwToQ(const int &bw);

    /*!
     *  @brief Q值转带宽
     *  @param Q值
     *  @return 带宽 * 100
    */
    static int qToBw(const double &q);
private:
    /*!
     * @brief 获取PEQ的dB和freq值
     * @param arg EQ参数
     * @return 键值对数组；key：freq，value：dB；freq源自EQ_FREQUENCY
     */

    static PairArray peq(const EQ &eq);
    /*!
     * @brief Hi_Shelf / Lo_Shelf  高架 / 低架
     */
    static PairArray hleq(const EQ &eq);

    static PairArray ap90();

    static PairArray ap180();

    static PairArray hpf(const Xover &xover);

    static PairArray lpf(const Xover &xover);

    static PairArray hlpf(const BiquadCoeffs &coeffs);

    static PairArray gainArray(const double &a1, const double &a2, const double &b0, const double &b1, const double &b2);
    static double calculateGain(const double &freq, const double &a1, const double &a2, const double &b0, const double &b1, const double &b2);
    static double getdB(const double &gain, const EQType &type);
    static double getBW(const uint16_t &bw);
    static size_t getFreqIndex(const double &target);
private:
    /**
     * @brief 阶数
     * @param type 滤波器类型
     * @param slope 斜率
     */
    static uint8_t order(PfType type, Slope slope);

    static double gain(double amplitude);

    // 求幅值的平方的倒数
    /**
     * @param n = slope ÷ 6 dB/oct          12dB/oct -> 2   24dB/oct -> 4   36dB/oct -> 6   48dB/oct -> 8
     * @param fc 截止频率
     * @param f 频率
     * @note 频率范围20 - 20000
     */
    static double butter_worth_lpf(uint8_t n, uint16_t fc, double f);
    static double butter_worth_hpf(uint8_t n, uint16_t fc, double f);
    static double linkwitz_riley_lpf(uint8_t n, uint16_t fc, double f);
    static double linkwitz_riley_hpf(uint8_t n, uint16_t fc, double f);
    // 计算n阶贝塞尔多项式在复数s处的值（使用std::complex）
    static cd bessel_hpf_polynomial(int order, const cd& s);
    static cd bessel_lpf_polynomial(int order, const cd& s);

    // 计算贝塞尔多项式在虚轴上的模值平方（s = j*x 时 |B_n(s)|²）
    static double bessel_hpf_magnitude_squared(int order, double x);
    static double bessel_lpf_magnitude_squared(int order, double x);

    // 计算高通滤波器增益（dB）
    static double bessel_hpf_gain(int order, double designCutoff, double freq);
    static double bessel_lpf_gain(int order, double designCutoff, double freq);

    // 反推设计参数：确保targetFreq处增益为-3dB
    static double bessel_hpf_design_cutoff(int order, double targetFreq);
    static double bessel_lpf_design_cutoff(int order, double targetFreq);

    static PairArray bessel_hpf(Slope slope, uint16_t fc);
    static PairArray bessel_lpf(Slope slope, uint16_t fc);
};

#endif // FILTER_H
